<?php
require_once 'lib/controllerWithoutGetOrPost.php';
require_once 'models/EmailModel.php';
require_once 'lib/PxPay_OpenSSL.inc.php';

# DATABASE METHODS

/**
 * Get the persons name from the database
 *
 * @return array[string]string
 * @param int $personId
 */
function getName($personId)
{
    global $db;
    $fullName = array(
        'firstNames' => '',
        'lastName' => ''
    );
    $sql = <<< EOT
        SELECT FirstNames, Surname
        FROM Person
        WHERE ID = %d
EOT;
    $sql = sprintf($sql, $personId);
    $result = $db->query($sql);
    if (!empty($result)) {
        $row = $db->fetch($result);
        $fullName['firstNames'] = $db->unescape($row['FirstNames']);
        $fullName['surname'] = $db->unescape($row['Surname']);
    }
    return $fullName;
}
/**
 * Check if a transaction has already been recorded
 *
 * @return bool
 * @param int $merchantReference
 */
function hasTransaction($merchantReference)
{
    global $db;
    $hasTransaction = FALSE;
    $sql = <<< EOT
        SELECT Success
        FROM DPSTransaction
        WHERE
            TxnType = 'Notice Summary' AND
            Success=1 AND
            ID = %d
EOT;
    $sql = sprintf($sql, $merchantReference);
    $result = $db->query($sql);
    if ($db->rowCount($result) > 0) {
        $hasTransaction = TRUE;
    }
    return $hasTransaction;
}
/**
 * Add order information to the database
 *
 * @return int
 * @param mixed $amountInput
 * @param mixed $txnData1
 * @param mixed $txnData2
 * @param mixed $txnData3
 * @param mixed $currencyInput
 * @param mixed $emailAddress
 */
function addOrder($amountInput, $txnData1, $txnData2, $txnData3, $currencyInput, $emailAddress)
{
    global $db;
    $amountInput = $db->escape($amountInput);
    $txnData1 = $db->escape($txnData1);
    $txnData2 = $db->escape($txnData2);
    $txnData3 = $db->escape($txnData3);
    $currencyInput = $db->escape($currencyInput);
    $emailAddress = $db->escape($emailAddress);
    $sql = <<< EOT
        INSERT
            INTO DPSTransaction (TxnType, Success, AmountSettlement, TxnData1, TxnData2, TxnData3, CurrencyInput, EmailAddress)
            VALUES ('Notice Summary', 0, '%s', '%s', '%s', '%s', '%s', '%s')

EOT;
    $sql = sprintf($sql,
        $amountInput,
        $txnData1,
        $txnData2,
        $txnData3,
        $currencyInput,
        $emailAddress
    );
    $result = $db->query($sql);
    $insertId = 0;
    if ($result === TRUE) {
        $insertId = $db->insertID();
    }
    return $insertId;
}
/**
 * Update order information to the database
 *
 * @return bool
 * @param int $success
 * @param mixed $amountSettlement
 * @param int $authCode
 * @param mixed $cardName
 * @param mixed $cardNumber
 * @param mixed $dateExpiry
 * @param mixed $dpsBillingId
 * @param mixed $billingId
 * @param mixed $cardHolderName
 * @param mixed $dpsTxnRef
 * @param mixed $txnData1
 * @param mixed $txnData2
 * @param mixed $txnData3
 * @param mixed $currencySettlement
 * @param mixed $clientInfo
 * @param mixed $txnId
 * @param mixed $currencyInput
 * @param mixed $emailAddress
 * @param int $merchantReference
 * @param mixed $responseText
 * @param mixed $txnMac
 */
function updateOrder($merchantReference, $success, $amountSettlement, $authCode, $cardName, $cardNumber, $dateExpiry, $dpsBillingId, $billingId, $cardHolderName, $dpsTxnRef, $txnData1, $txnData2, $txnData3, $currencySettlement, $clientInfo, $txnId, $currencyInput, $emailAddress, $responseText, $txnMac)
{
    global $db;
    $sql = <<< EOT
        UPDATE DPSTransaction
            SET
                Success = %d,
                AmountSettlement = '%s',
                AuthCode = %d,
                CardName = '%s',
                CardNumber = '%s',
                DateExpiry = '%s',
                DpsBillingId = '%s',
                BillingId = '%s',
                CardHolderName = '%s',
                DpsTxnRef = '%s',
                TxnData1 = '%s',
                TxnData2 = '%s',
                TxnData3 = '%s',
                CurrencySettlement = '%s',
                ClientInfo = '%s',
                TxnId = '%s',
                CurrencyInput = '%s',
                EmailAddress = '%s',
                ResponseText = '%s',
                TxnMac = '%s'
        WHERE ID = %d
EOT;
    $sql = sprintf($sql,
        $success,
        $db->escape($amountSettlement),
        $authCode,
        $db->escape($cardName),
        $db->escape($cardNumber),
        $db->escape($dateExpiry),
        $db->escape($dpsBillingId),
        $db->escape($billingId),
        $db->escape($cardHolderName),
        $db->escape($dpsTxnRef),
        $db->escape($txnData1),
        $db->escape($txnData2),
        $db->escape($txnData3),
        $db->escape($currencySettlement),
        $db->escape($clientInfo),
        $db->escape($txnId),
        $db->escape($currencyInput),
        $db->escape($emailAddress),
        $db->escape($responseText),
        $db->escape($txnMac),
        $merchantReference
    );
   $result = $db->query($sql);
    return $result === TRUE;
}
/**
 * @return array[string]string
 */
function getPxPayValues()
{
    global $db;
    $values = /*.(array[string]string) .*/array();
    $sql = <<< EOT
        SELECT Name, Value
        FROM Local
        WHERE Name LIKE 'pxPay%'
EOT;
    $result = $db->query($sql);
    if ($db->rowCount($result) > 0) {
        while (TRUE) {
            $row = $db->fetch($result);
            if (empty($row)) {
                break;
            }
            $values[$row['Name']] = $db->unescape($row['Value']);
        }
    }
    return $values;
}

# VIEW METHODS

/** Show an important notice
 *
 * @return string
 * @param string $content
 */
function importantNotice($content)
{
    return <<< EOT
        <div class="important">
            <h2>Important Notice</h2>
            $content
        </div>
        
EOT;
}
/** A link to the page to process the order
 *
 * @return string
 * @param int $merchantReference
 */
function viewProcessOrder($merchantReference)
{
    return <<< EOT
    <p>Process order: <a href="http://www.amemorytree.co.nz/admin/noticeSummary.php?transId=$merchantReference">http://www.amemorytree.co.nz/admin/noticeSummary.php?transId=$merchantReference</a></p>
EOT;
}
/** The order receipt
 *
 * @return string
 * @param int $authCode
 * @param string $amountSettlement
 * @param string $currencyInput
 * @param string $customerEmail
 * @param string $clientInfo
 * @param string $papers
 * @param string $fullName
 * @param string $cardName
 * @param string $cardHolderName
 *
 */
function viewReceipt($authCode, $amountSettlement, $currencyInput, $customerEmail, $clientInfo, $papers, $fullName, $cardName, $cardHolderName)
{
    return <<< EOT
    <h2>Receipt</h2>
    <p>Receipt #: $authCode</p>
    <p>GST: 95-288-030</p>
    <p>Sum of: $$amountSettlement $currencyInput</p>
    <p>From: $customerEmail - IP address: $clientInfo</p>
    <p>For: Notice Summary from $papers for $fullName
    <p>Card Type: $cardName</p>
    <p>Card Name: $cardHolderName</p>

EOT;
}

# MODEL METHODS

/**
 * Provide the full name for the person
 *
 * @return string
 * @param int $personId
 */
function getFullName($personId)
{
    $name = getName($personId);
    $firstNames = $name['firstNames'];
    $surname = $name['surname'];
    return "$firstNames $surname";
}
/**
 * A comma separated list, with "and" before the last term.
 *
 * @return string
 * @param array[int]string $terms
 */
function commaSeparate($terms)
{
    $commaSeparated = '';
    if (!empty($terms)) {
        $commaSeparated .= (string)array_pop($terms);
    }
    if (!empty($terms)) {
        $commaSeparated = (string)array_pop($terms).', and '.$commaSeparated;
    }
    if (!empty($terms)) {
        $remainder = implode(', ', $terms);
        $commaSeparated = $remainder.', '.$commaSeparated;
    }
    return $commaSeparated;
}
/**
 * Send an email
 *
 * @return bool
 * @param string $fromName
 * @param string $fromEmail
 * @param string $toName
 * @param string $toEmail
 * @param string $subject
 * @param string $message
 */
function sendEmail($fromName, $fromEmail, $toName, $toEmail, $subject, $message)
{
    $email = new EmailModel();
    $email->setFromName($fromName);
    $email->setFromEmail($fromEmail);
    $email->setToName($toName);
    $email->setToEmail($toEmail);
    $email->setSubject($subject);
    $email->setMessage($message);
    return $email->send();
}
/**
 * Send an email to the customer
 *
 * @return bool
 * @param string $toEmail
 * @param string $fullName
 * @param string $message
 */
function sendCustomerEmail($toEmail, $fullName, $message) {
    $fromName = 'A Memory Tree';
    $fromEmail = 'order@amemorytree.co.nz';
    $toName = $toEmail;
    $subject = "Death Notice Summary Order for $fullName";
    $message = '<p>Thank you for your order.</p>'.$message;
    return sendEmail($fromName, $fromEmail, $toName, $toEmail, $subject, $message);
}
/**
 * Send an email to our business
 *
 * @return bool
 * @param int $merchantReference
 * @param string $customerEmail
 * @param string $fullName
 * @param string $message
 */
function sendBusinessEmail($merchantReference, $customerEmail, $fullName, $message) {
    $fromName = 'A Memory Tree';
    $fromEmail = 'order@amemorytree.co.nz';
    $toName = $fromName;
    $toEmail = $fromEmail;
    $subject = "Death Notice Summary Order $merchantReference, from $customerEmail for $fullName";
    return sendEmail($fromName, $fromEmail, $toName, $toEmail, $subject, $message);
}
/**
 * Show the result of the order
 *
 * @return string
 * @param PxPay_OpenSSL &$pxpay
 */
function print_result(&$pxpay)
{
    $enc_hex = strval($_REQUEST["result"]);
    #getResponse method in PxPay object returns PxPayResponse object
    #which encapsulates all the response data
    /*.PxPayResponse.*/ $rsp  = $pxpay->getResponse($enc_hex);
    $merchantReference  = intval($rsp->getMerchantReference());
    $success            = intval($rsp->getSuccess());   # =1 when request succeeds
    $amountSettlement   = strval($rsp->getAmountSettlement());
    $authCode           = intval($rsp->getAuthCode());  # from bank
    $cardName           = strval($rsp->getCardName());  # e.g. "Visa"
    $cardNumber         = strval($rsp->getCardNumber()); # Truncated card number
    $dateExpiry         = strval($rsp->getDateExpiry()); # in mmyy format
    $dpsBillingId       = strval($rsp->getDpsBillingId());
    $billingId          = strval($rsp->getBillingId());
    $cardHolderName     = strval($rsp->getCardHolderName());
    $dpsTxnRef          = strval($rsp->getDpsTxnRef());
    $txnData1           = strval($rsp->getTxnData1());
    $txnData2           = strval($rsp->getTxnData2());
    $txnData3           = strval($rsp->getTxnData3());
    $currencySettlement = strval($rsp->getCurrencySettlement());
    $clientInfo         = strval($rsp->getClientInfo()); # The IP address of the user who submitted the transaction
    $txnId              = strval($rsp->getTxnId());
    $currencyInput      = strval($rsp->getCurrencyInput());
    $emailAddress       = strval($rsp->getEmailAddress());
    $responseText       = strval($rsp->getResponseText());
    $txnMac             = strval($rsp->getTxnMac()); # An indication as to the uniqueness of a card used in relation to others

    $personId = intval($txnData1);
    $publications = $txnData2;

    $fullName = getFullName($personId);
    $remembrancePage = '<a href="remembrance.php?personid='.$personId.'">'.$fullName.'</a>';
    $personNotices = '<a href="personnotices.php?personid='.$personId.'">'.$fullName.'</a>';
    $publications = commaSeparate(explode('|', $publications));
    
    $style = <<< EOT
    <style type="text/css">
    #contentarea #centerbar div.important { border: 1px solid #C12A0B; margin: 0.5em 0; }
    #contentarea #centerbar div.important h2 { background: #B80101; color: white; padding: 0.5em; }
    #contentarea #centerbar div.important p { margin: 0.5em; }
    .heading { color: #C12A0B; font-weight: bold; }
    </style>

EOT;
    $successMessage = <<< EOT
    <h2>Purchase Successful</h2>
    <p>Thank you. Your receipt has been emailed to you. (A copy is shown below)</p>
    <p>Back to $remembrancePage remembrance page.</p>

EOT;
    $unsuccessfulMessage = <<< EOT
    <h2>Your Purchase was Unsuccessful</h2>
    <p>We're sorry. There has been a problem with your payment. Please reenter your request at $personNotices notices page.</p>
EOT;

    if ($rsp->getSuccess() === "1") {
        $spamNotice = '<p><span class="heading">SPAM</span> - Spam filters on your email can sometimes wrongly detect A Memory Tree emails as spam. If you do not receive you order by email within 24 hours, please check you Junk Mail, Spam, or Bulk folders.  Also please contact your mail administrator to discuss how to prevent A Memory Tree emailed being incorrectly classified as spam.</p>';
        $waitNotice = '<p><span class="heading">PLEASE WAIT 24 HOURS</span> - Summaries of death notices are not automated. A real person compiles this especially for you. Please allow 24 hours for deliver. Check your Spam if longer than 24 hours or contact us at <a href="mailto:order@amemorytree.co.nz">order@amemorytree.co.nz</a></p>';
        $receiptNotice = '<p><span class="heading">RECEIPT</span> - A receipt was automatically emailed to you when your payment was accepted. Details of your purchase including GST component is in that email.</p>';
        $pageNotice = importantNotice($spamNotice.$waitNotice.$receiptNotice);
        $emailNotice = importantNotice($waitNotice);
        $customerEmail = $txnData3;
        $receipt = viewReceipt($merchantReference, $amountSettlement, $currencyInput, $customerEmail, $clientInfo, $publications, $fullName, $cardName, $cardHolderName);
        if (!hasTransaction($merchantReference)) {
            updateOrder($merchantReference, $success, $amountSettlement, $authCode, $cardName, $cardNumber, $dateExpiry, $dpsBillingId, $billingId, $cardHolderName, $dpsTxnRef, $txnData1, $txnData2, $txnData3, $currencySettlement, $clientInfo, $txnId, $currencyInput, $emailAddress, $responseText, $txnMac);
            $process = viewProcessOrder($merchantReference);
            $businessMessage = $process.$emailNotice.$receipt;
            $customerMessage = $receipt.$emailNotice;
            sendBusinessEmail($merchantReference, $customerEmail, $fullName, $businessMessage);
            sendCustomerEmail($customerEmail, $fullName, $customerMessage);
        }
        $text = $style.$successMessage.$pageNotice.$receipt;
    } else {
        $text = $unsuccessfulMessage;
    }
    return '<div id="centerbar">'.$text.'</div>';
}
/**
 * Redirect to the payment website
 *
 * @return void
 * @param PxPay_OpenSSL $pxpay
 */
function redirect_form($pxpay)
{
    global $db;

    $request = new PxPayRequest();

    $http_host   = getenv("HTTP_HOST");
    $request_uri = getenv("SCRIPT_NAME");
    $server_url  = "http://$http_host";
    $script_url = (version_compare(PHP_VERSION, "4.3.4", ">=") === TRUE) ?"$server_url$request_uri" : "$server_url/$request_uri";

    $personId = intval($_GET['personid']);
    $postedPublications = /*. (array[int]string) .*/ $_GET['publication'];
    $quantity = count($postedPublications);
    $publications = $db->escape(implode(' | ', $postedPublications));
    $email = $db->escape($_GET['email']);
    $confirmEmail = $db->escape($_GET['confirmEmail']);

    $errors = '';
    if (empty($personId)) {
        $errors .= '&personiderror=yes';
        //array_push($errors, 'Internal error: The person id needs to provided.');
    }
    if ($quantity < 1) {
        $errors .= '&publicationerror=yes';
        //array_push($errors, 'No publication is selected. Please select a publication.');
    }
    if (empty($email)) {
        $errors .= '&emailprovidederror=yes';
    } else if ($email !== $confirmEmail) {
        $errors .= '&emailmatcherror=yes';
        //array_push($errors, 'The email addresses do not match.');
    }
    if (!empty($errors)) {
        $host = $_SERVER['HTTP_HOST'];
        $path = '/personnotices.php';
        $query = $_SERVER['QUERY_STRING'];
        header("Location: HTTP://$host$path?$query$errors#orderNotice");
    } else {
        $amountInput = 4.90 * $quantity;
        $txnType = 'Purchase';  
        $txnData1 = strval($personId);
        $txnData2 = $publications;
        $txnData3 = $email;
        $currencyInput = 'NZD';
        $emailAddress = 'theteam@amemorytree.co.nz';
       
        $txnId = uniqid("ID");
        $request->setAmountInput($amountInput);
        $request->setTxnType($txnType);
        $request->setTxnData1($txnData1);
        $request->setTxnData2($txnData2);
        $request->setTxnData3($txnData3);
        $request->setCurrencyInput($currencyInput);
        $request->setEmailAddress($emailAddress);
        $request->setUrlFail($script_url);			# can be a dedicated failure page
        $request->setUrlSuccess($script_url);			# can be a dedicated success page
        $request->setTxnId($txnId);  

        $merchantReference = addOrder($amountInput, $txnData1, $txnData2, $txnData3, $currencyInput, $emailAddress);
        $request->setMerchantReference(strval($merchantReference));

        #The following properties are not used in this case
        # $request->setEnableAddBillCard($EnableAddBillCard);    
        # $request->setBillingId($BillingId);
        # $request->setOpt($Opt);

        // obtain input XML
        $request_string = $pxpay->makeRequest($request);

        //Obtain output XML
        $response = new MifMessage($request_string);

        // Parse output XML
        $url = $response->get_element_text("URI");
        //$valid = $response->get_attribute("valid");

        // Redirect to payment page
        header("Location: ".$url);
    }
}
$pxPayValues = getPxPayValues();
$pxPayUrl = $pxPayValues['pxPayUrl'];
$pxPayUserId = $pxPayValues['pxPayUserId'];
$pxPayKey = $pxPayValues['pxPayKey'];
$pxpay = new PxPay_OpenSSL($pxPayUrl, $pxPayUserId, $pxPayKey);
if (isset($_REQUEST["result"])) {
    require_once 'view/standard-top.php';
    echo print_result($pxpay);
    require_once 'view/standard-bottom.php';
} elseif (isset($_REQUEST["Submit"])) {
    redirect_form($pxpay);
}
?>
